import type { Metadata } from 'next'; import { notFound, permanentRedirect } from 'next/navigation'; import { loadCancer, TABS, type TabKey } from '@/components/cancer/load'; import { CancerHeader } from '@/components/cancer/header'; import { OverviewTab } from '@/components/cancer/tabs/overview'; import { StatisticsTab } from '@/components/cancer/tabs/statistics'; import { SurvivalTab } from '@/components/cancer/tabs/survival'; import { GenomicsTab } from '@/components/cancer/tabs/genomics'; import { EvidenceTab } from '@/components/cancer/tabs/evidence'; import { DrugsTab } from '@/components/cancer/tabs/drugs'; import { TrialsTab } from '@/components/cancer/tabs/trials'; import { ResearchTab } from '@/components/cancer/tabs/research'; import { RankingsTab } from '@/components/cancer/tabs/rankings'; import { SourcesTab } from '@/components/cancer/tabs/sources'; import { jsonLd, medicalConditionLd } from '@/lib/seo'; import { str, int, type SP } from '@/lib/search-params'; import { truncate } from '@/lib/format'; export const revalidate = 3600; export const dynamicParams = true; type Params = { slug: string; tab?: string[] }; function tabKey(tab: string[] | undefined): TabKey | null { const t = tab?.[0] ?? 'overview'; if (tab && tab.length > 1) return null; return TABS.some((x) => x.key === t) ? (t as TabKey) : null; } export async function generateMetadata({ params }: { params: Promise }): Promise { const { slug, tab } = await params; const b = await loadCancer(slug); if (!b) return { title: 'Not found' }; const key = tabKey(tab) ?? 'overview'; const label = TABS.find((t) => t.key === key)?.label ?? ''; const desc = b.cancer.description ? truncate(b.cancer.description, 160) : `${b.cancer.canonical_name} (${b.cancer.id}): taxonomy, statistics, genomics, evidence, drugs, trials, literature and rankings with full provenance.`; return { title: key === 'overview' ? b.cancer.canonical_name : `${b.cancer.canonical_name} — ${label}`, description: desc, alternates: { canonical: key === 'overview' ? `/cancer/${b.cancer.slug}` : `/cancer/${b.cancer.slug}/${key}` }, }; } export default async function CancerPage({ params, searchParams }: { params: Promise; searchParams: Promise }) { const { slug, tab } = await params; const key = tabKey(tab); if (!key) notFound(); const b = await loadCancer(slug); if (!b) notFound(); if (b.cancer.slug !== slug) permanentRedirect(key === 'overview' ? `/cancer/${b.cancer.slug}` : `/cancer/${b.cancer.slug}/${key}`); let body: React.ReactNode; switch (key) { case 'statistics': body = ; break; case 'survival': body = ; break; case 'genomics': { const sp = await searchParams; body = ; break; } case 'evidence': { const sp = await searchParams; body = ; break; } case 'drugs': { const sp = await searchParams; body = ; break; } case 'trials': { const sp = await searchParams; body = ; break; } case 'research': { const sp = await searchParams; body = ; break; } case 'rankings': body = ; break; case 'sources': body = ; break; default: body = ; } const ld = medicalConditionLd({ slug: b.cancer.slug, canonicalName: b.cancer.canonical_name, description: b.cancer.description, aliases: b.aliases.filter((a) => a.alias_type !== 'preferred').map((a) => a.alias), codes: b.codes }); return (